home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Comm / www / tidy_os4.lha / tidy / console / tab2space.c next >
C/C++ Source or Header  |  2004-07-25  |  7KB  |  362 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #include "platform.h"
  6.  
  7. #define true       1
  8. #define false      0
  9. #define TABSIZE    4
  10.  
  11. #define DOS_CRLF   0
  12. #define UNIX_LF    1
  13. #define MAC_CR     2
  14.  
  15. typedef struct
  16. {
  17.     Bool pushed;
  18.     int tabs;
  19.     int curcol;
  20.     int lastcol;
  21.     int maxcol;
  22.     int curline;
  23.     int pushed_char;
  24.     uint size;
  25.     uint length;
  26.     char *buf;
  27.     FILE *fp;
  28. } Stream;
  29.  
  30. int tabsize = TABSIZE;
  31. int endline = DOS_CRLF;
  32. Bool tabs = false;
  33.  
  34. /*
  35.  Memory allocation functions vary from one environment to
  36.  the next, and experience shows that wrapping the local
  37.  mechanisms up provides for greater flexibility and allows
  38.  out of memory conditions to be detected in one place.
  39. */
  40. void *MemAlloc(size_t size)
  41. {
  42.     void *p;
  43.  
  44.     p = malloc(size);
  45.  
  46.     if (!p)
  47.     {
  48.         fprintf(stderr, "***** Out of memory! *****\n");
  49.         exit(1);
  50.     }
  51.  
  52.     return p;
  53. }
  54.  
  55. void *MemRealloc(void *old, size_t size)
  56. {
  57.     void *p;
  58.  
  59.     p = realloc(old, size);
  60.  
  61.     if (!p)
  62.     {
  63.         fprintf(stderr, "***** Out of memory! *****\n");
  64.         return NULL;
  65.     }
  66.  
  67.     return p;
  68. }
  69.  
  70. void MemFree(void *p)
  71. {
  72.     free(p);
  73.     p = NULL;
  74. }
  75.  
  76. Stream *NewStream(FILE *fp)
  77. {
  78.     Stream *in;
  79.  
  80.     in = (Stream *)MemAlloc(sizeof(Stream));
  81.  
  82.     memset(in, 0, sizeof(Stream));
  83.     in->fp = fp;
  84.     return in;
  85. }
  86.  
  87. void FreeStream(Stream *in)
  88. {
  89.     if (in->buf)
  90.         MemFree(in->buf);
  91.  
  92.     MemFree(in);
  93. }
  94.  
  95. void AddByte(Stream *in, uint c)
  96. {
  97.     if (in->size + 1 >= in->length)
  98.     {
  99.         while (in->size + 1 >= in->length)
  100.         {
  101.             if (in->length == 0)
  102.                 in->length = 8192;
  103.             else
  104.                 in->length = in->length * 2;
  105.         }
  106.  
  107.         in->buf = (char *)MemRealloc(in->buf, in->length*sizeof(char));
  108.     }
  109.  
  110.     in->buf[in->size++] = (char)c;
  111.     in->buf[in->size] = '\0';  /* debug */
  112. }
  113.  
  114.  
  115.  
  116. /*
  117.   Read a character from a stream, keeping track
  118.   of lines, columns etc. This is used for parsing
  119.   markup and plain text etc. A single level
  120.   pushback is allowed with UngetChar(c, in).
  121.   Returns EndOfStream if there's nothing more to read.
  122. */
  123. int ReadChar(Stream *in)
  124. {
  125.     uint c;
  126.  
  127.     if (in->pushed)
  128.     {
  129.         in->pushed = false;
  130.  
  131.         if (in->pushed_char == '\n')
  132.             in->curline--;
  133.  
  134.         return in->pushed_char;
  135.     }
  136.  
  137.     in->lastcol = in->curcol;
  138.  
  139.     /* expanding tab ? */
  140.     if (in->tabs > 0)
  141.     {
  142.         in->curcol++;
  143.         in->tabs--;
  144.         return ' ';
  145.     }
  146.     
  147.     /* Else go on with normal buffer: */
  148.     for (;;)
  149.     {
  150.         c = getc(in->fp);
  151.  
  152.         /* end of file? */
  153.         if (c == EOF)
  154.             break;
  155.  
  156.         /* coerce \r\n  and isolated \r as equivalent to \n : */
  157.         if (c == '\r')
  158.         {
  159.             c = getc(in->fp);
  160.  
  161.             if (c != '\n')
  162.                 ungetc(c, in->fp);
  163.  
  164.             c = '\n';
  165.         }
  166.  
  167.         if (c == '\n')
  168.         {
  169.             if (in->maxcol < in->curcol)
  170.                 in->maxcol = in->curcol;
  171.  
  172.             in->curcol = 1;
  173.             in->curline++;
  174.             break;
  175.         }
  176.  
  177.         if (c == '\t')
  178.         {
  179.             if (tabs)
  180.               in->curcol += tabsize - ((in->curcol - 1) % tabsize);
  181.             else /* expand to spaces */
  182.             {
  183.                 in->tabs = tabsize - ((in->curcol - 1) % tabsize) - 1;
  184.                 in->curcol++;
  185.                 c = ' ';
  186.             }
  187.  
  188.             break;
  189.         }
  190.  
  191.         if (c == '\033')
  192.             break;
  193.  
  194.         /* strip control characters including '\r' */
  195.  
  196.         if (0 < c && c < 32)
  197.             continue;
  198.  
  199.         in->curcol++;
  200.         break;
  201.     }
  202.  
  203.     return c;
  204. }
  205.  
  206. Stream  *ReadFile(FILE *fin)
  207. {
  208.     int c;
  209.     Stream *in  = NewStream(fin);
  210.  
  211.     while ((c = ReadChar(in)) >= 0)
  212.         AddByte(in, (uint)c);
  213.  
  214.     return in;
  215. }
  216.  
  217. void WriteFile(Stream *in, FILE *fout)
  218. {
  219.     int i, c;
  220.     char *p;
  221.  
  222.     i = in->size;
  223.     p = in->buf;
  224.  
  225.     while (i--)
  226.     {
  227.         c = *p++;
  228.  
  229.         if (c == '\n')
  230.         {
  231.             if (endline == DOS_CRLF)
  232.             {
  233.                 putc('\r', fout);
  234.                 putc('\n', fout);
  235.             }
  236.             else if (endline == UNIX_LF)
  237.                 putc('\n', fout);
  238.             else if (endline == MAC_CR)
  239.                 putc('\r', fout);
  240.  
  241.             continue;
  242.         }
  243.  
  244.         putc(c, fout);
  245.     }
  246. }
  247.  
  248. void HelpText(FILE *errout, char *prog)
  249. {
  250.     fprintf(errout, "%s: [options] [infile [outfile]] ...\n", prog);
  251.     fprintf(errout, "Utility to expand tabs and ensure consistent line endings\n");
  252.     fprintf(errout, "options for tab2space vers: 6th February 2003\n");
  253.     fprintf(errout, "  -help or -h     display this help message\n");
  254.     fprintf(errout, "  -dos  or -crlf  set line ends to CRLF (PC-DOS/Windows - default)\n");
  255.     fprintf(errout, "  -mac  or -cr    set line ends to CR (classic Mac OS)\n");
  256.     fprintf(errout, "  -unix or -lf    set line ends to LF (Unix)\n");
  257.     fprintf(errout, "  -tabs           preserve tabs, e.g. for Makefile\n");
  258.     fprintf(errout, "  -t<n>           set tabs to <n> (default is 4) spaces\n");
  259.     fprintf(errout, "\nNote this utility doesn't map spaces to tabs!\n");
  260. }
  261.  
  262. int main(int argc, char **argv)
  263. {
  264.     char *infile, *outfile, *prog;
  265.     FILE *fin, *fout;
  266.     Stream *in = NULL;
  267.  
  268.     prog = argv[0];
  269.  
  270.     while (argc > 0)
  271.     {
  272.         if (argc > 1 && argv[1][0] == '-')
  273.         {
  274.             if (strcmp(argv[1], "-help") == 0 || argv[1][1] == 'h')
  275.             {
  276.                 HelpText(stdout, prog);
  277.                 return 1;
  278.             }
  279.  
  280.             if (strcmp(argv[1], "-dos") == 0 ||
  281.                 strcmp(argv[1], "-crlf") == 0)
  282.                  endline = DOS_CRLF;
  283.  
  284.             else if (strcmp(argv[1], "-mac") == 0 ||
  285.                 strcmp(argv[1], "-cr") == 0)
  286.                 endline = MAC_CR;
  287.  
  288.             else if (strcmp(argv[1], "-unix") == 0 ||
  289.                 strcmp(argv[1], "-lf") == 0)
  290.                 endline = UNIX_LF;
  291.  
  292.             else if (strcmp(argv[1], "-tabs") == 0)
  293.                 tabs = true;
  294.  
  295.             else if (strncmp(argv[1], "-t", 2) == 0)
  296.                 sscanf(argv[1]+2, "%d", &tabsize);
  297.  
  298.             --argc;
  299.             ++argv;
  300.             continue;
  301.         }
  302.  
  303.         if (argc > 1)
  304.         {
  305.             infile = argv[1];
  306.             fin = fopen(infile, "rb");
  307.         }
  308.         else
  309.         {
  310.             infile = "stdin";
  311.             fin = stdin;
  312.         }
  313.  
  314.         if (argc > 2)
  315.         {
  316.             outfile = argv[2];
  317.             fout = NULL;
  318.             --argc;
  319.             ++argv;
  320.         }
  321.         else
  322.         {
  323.             outfile = "stdout";
  324.             fout = stdout;
  325.         }
  326.  
  327.         if (fin)
  328.         {
  329.             in = ReadFile(fin);
  330.  
  331.             if (fin != stdin)
  332.                 fclose(fin);
  333.             
  334.             if (fout != stdout)
  335.                fout = fopen(outfile, "wb");
  336.             
  337.             if (fout)
  338.             {
  339.                WriteFile(in, fout);
  340.                 
  341.                if (fout != stdout)
  342.                   fclose(fout);
  343.             }
  344.             else
  345.                 fprintf(stderr, "%s - can't open \"%s\" for writing\n", prog, outfile);
  346.  
  347.             FreeStream(in);
  348.         }
  349.         else
  350.             fprintf(stderr, "%s - can't open \"%s\" for reading\n", prog, infile);
  351.  
  352.         --argc;
  353.         ++argv;
  354.         
  355.         if (argc <= 1)
  356.             break;
  357.     }
  358.  
  359.     return 0;
  360. }
  361.  
  362.